﻿// Decompiled with JetBrains decompiler
// Type: Netick.CodeGen.NetickILProcessor
// Assembly: Netick.CodeGen, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 95965C71-875F-44B8-BA79-93A19C7D6A17
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Editor\Netick.CodeGen.dll

using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Mono.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

#nullable disable
namespace Netick.CodeGen;

public sealed class NetickILProcessor
{
  private const string ModifiedByNetick = "___ModifiedByNetick";
  private ICodeGenUser GameEngineWeaver;
  private RpcProcessor RpcProcessor = new RpcProcessor();
  private Dictionary<string, CodeGenOnChanged> PropertyToOnChangedEventHandler = new Dictionary<string, CodeGenOnChanged>(32 /*0x20*/);
  internal List<TypeDefinition> NetickBehaviours = new List<TypeDefinition>(512 /*0x0200*/);
  private TypeReference NetworkBehaviourType;
  private TypeReference ChangedInfoType;
  private TypeReference EntityTypeRef;
  private TypeReference InterpolatorTypeRef;
  private TypeReference systemString;
  private TypeReference systemStringBuilder;
  private TypeReference systemChar;
  private MethodReference loadStringFromPtr;
  private MethodReference setPtrString;
  private MethodReference onChangedCtor;
  private MethodReference ptr;
  private MethodReference dirtfy;
  private MethodReference addOnChanged;
  private MethodReference addSmooth;
  private MethodReference networkArrayinternalInit;
  private MethodReference networkArrayinternalReset;

  public void Init(ICodeGenUser engineWeaver, ModuleDefinition moduleDefinition)
  {
    this.GameEngineWeaver = engineWeaver;
    this.RpcProcessor.Init(engineWeaver, moduleDefinition);
  }

  public bool ProcessAssembly(AssemblyDefinition assemblyDefinition)
  {
    ModuleDefinition mainModule = assemblyDefinition.MainModule;
    if (mainModule == null)
      return false;
    if (((IEnumerable<TypeDefinition>) mainModule.Types).Where<TypeDefinition>((Func<TypeDefinition, bool>) (type => ((MemberReference) type).Name == "___ModifiedByNetick")).FirstOrDefault<TypeDefinition>() != null)
      return true;
    this.NetworkBehaviourType = mainModule.ImportReference(typeof (INetickNetworkScript));
    this.ChangedInfoType = mainModule.ImportReference(typeof (Netick.OnChangedData));
    this.InterpolatorTypeRef = mainModule.ImportReference(typeof (Interpolator));
    this.loadStringFromPtr = mainModule.ImportReference((MethodBase) typeof (NetickUtils).GetMethod("LoadStringFromPtr"));
    this.setPtrString = mainModule.ImportReference((MethodBase) typeof (NetickUtils).GetMethod("SetPtrString"));
    this.onChangedCtor = mainModule.ImportReference((MethodReference) TypeDefinitionRocks.GetConstructors(mainModule.ImportReference(typeof (OnChangedEvent)).Resolve()).FirstOrDefault<MethodDefinition>());
    this.ptr = mainModule.ImportReference((MethodBase) typeof (INetickNetworkScript).GetProperty("State").GetMethod);
    this.dirtfy = mainModule.ImportReference((MethodBase) typeof (Entity).GetMethod("InternalDirtify"));
    this.addOnChanged = mainModule.ImportReference((MethodBase) typeof (Entity).GetMethod("InternalRegOnChanged"));
    this.addSmooth = mainModule.ImportReference((MethodBase) typeof (Entity).GetMethod("InternalRegSmooth"));
    this.networkArrayinternalInit = mainModule.ImportReference((MethodBase) typeof (INetworkCollection).GetMethod("InternalInit"));
    this.networkArrayinternalReset = mainModule.ImportReference((MethodBase) typeof (INetworkCollection).GetMethod("InternalReset"));
    this.systemString = mainModule.ImportReference(typeof (string));
    this.systemStringBuilder = mainModule.ImportReference(typeof (StringBuilder));
    this.systemChar = mainModule.ImportReference(typeof (char));
    this.NetickBehaviours = new List<TypeDefinition>(512 /*0x0200*/);
    HashSet<ModuleDefinition> moduleDefinitionSet = new HashSet<ModuleDefinition>(32 /*0x20*/);
    HashSet<TypeDefinition> typeDefinitionSet = new HashSet<TypeDefinition>(1024 /*0x0400*/);
    foreach (TypeDefinition type1 in mainModule.Types)
    {
      if (type1.BaseType != null)
      {
        ModuleDefinition module = ((MemberReference) type1.BaseType.Resolve()).Module;
        if (((MemberReference) type1).Module.Assembly.Name != module.Assembly.Name && !moduleDefinitionSet.Contains(module) && this.IsNetworkBehaviour(type1) && ((MemberReference) type1.BaseType).FullName != this.GameEngineWeaver.GetNetworkScriptTypeFullName())
        {
          moduleDefinitionSet.Add(module);
          foreach (TypeDefinition type2 in module.Types)
          {
            bool flag = ((IEnumerable<CustomAttribute>) type2.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>() != null;
            if (this.IsNetworkBehaviour(type2))
              typeDefinitionSet.Add(type2);
            else if (flag && ((TypeReference) type2).IsValueType)
              typeDefinitionSet.Add(type2);
          }
        }
        bool flag1 = ((IEnumerable<CustomAttribute>) type1.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>() != null;
        if (this.IsNetworkBehaviour(type1) || flag1 && ((TypeReference) type1).IsValueType)
          typeDefinitionSet.Add(type1);
      }
    }
    foreach (TypeDefinition typeDefinition in typeDefinitionSet)
    {
      if (this.IsNetworkBehaviour(typeDefinition))
        this.NetickBehaviours.Add(typeDefinition);
      else if (this.IsNetworkStruct(typeDefinition))
        this.ProcessNetworkStruct(typeDefinition);
      foreach (TypeDefinition nestedType in typeDefinition.NestedTypes)
      {
        if (this.IsNetworkStruct(nestedType))
          this.ProcessNetworkStruct(nestedType);
      }
    }
    foreach (TypeDefinition netickBehaviour in this.NetickBehaviours)
      this.ProcessRootBehaviour(this.GameEngineWeaver, mainModule, netickBehaviour);
    if (this.NetickBehaviours.Count <= 0)
      return false;
    this.AddNetickCodeGenMark(mainModule);
    return true;
  }

  private bool IsNetworkBehaviour(TypeDefinition type)
  {
    return type.IsSubclassOf(this.GameEngineWeaver.GetNetworkScriptTypeFullName());
  }

  private bool IsNetworkStruct(TypeDefinition type)
  {
    return ((IEnumerable<CustomAttribute>) type.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>() != null;
  }

  private void AddNetickCodeGenMark(ModuleDefinition def)
  {
    TypeDefinition typeDefinition = new TypeDefinition("", "___ModifiedByNetick", (TypeAttributes) 1179649, def.ImportReference(typeof (object)));
    def.Types.Add(typeDefinition);
  }

  private void ProcessRootBehaviour(
    ICodeGenUser engineWeaver,
    ModuleDefinition module,
    TypeDefinition t)
  {
    int size = 0;
    if (!this.IsRootBehaviour(module, t, out size))
      return;
    this.ProcessTree(engineWeaver, size, module, t);
  }

  private int ProcessTree(
    ICodeGenUser engineWeaver,
    int wordSize,
    ModuleDefinition module,
    TypeDefinition root)
  {
    int wordSize1 = this.ProcessNetworkBehaviour(engineWeaver, root, wordSize);
    foreach (TypeDefinition type in module.Types)
    {
      bool flag = false;
      if (type.BaseType != null)
        flag = ((MemberReference) type.BaseType.Resolve()).FullName == ((MemberReference) root).FullName;
      if (flag && type.BaseType != null)
        this.ProcessTree(engineWeaver, wordSize1, module, type);
    }
    return wordSize1;
  }

  private bool IsRootBehaviour(ModuleDefinition module, TypeDefinition t, out int size)
  {
    size = 0;
    return t.IsSubclassOf(this.GameEngineWeaver.GetNetworkScriptTypeFullName()) && t.BaseType != null && (((MemberReference) t.BaseType).FullName == this.GameEngineWeaver.GetNetworkScriptTypeFullName() || module != ((MemberReference) t).Module);
  }

  internal int ProcessNetworkBehaviour(
    ICodeGenUser gameEngineCodeGen,
    TypeDefinition typeDefinition,
    int wordSize)
  {
    if (((IEnumerable<CustomAttribute>) typeDefinition.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (IgnoreCodeGen).FullName)).FirstOrDefault<CustomAttribute>() != null)
      return wordSize;
    this.GameEngineWeaver = gameEngineCodeGen;
    this.PropertyToOnChangedEventHandler.Clear();
    this.ProcessOnChangeMethods(typeDefinition);
    MethodDefinition overridableMethod1 = this.GetOverridableMethod(typeDefinition, "InternalInit");
    MethodDefinition overridableMethod2 = this.GetOverridableMethod(typeDefinition, "InternalReset");
    int num1 = wordSize;
    List<PropertyDefinition> propertyDefinitionList = new List<PropertyDefinition>();
    foreach (PropertyDefinition property in typeDefinition.Properties)
    {
      CustomAttribute customAttribute1 = ((IEnumerable<CustomAttribute>) property.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>();
      CustomAttribute customAttribute2 = ((IEnumerable<CustomAttribute>) property.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Smooth).FullName)).FirstOrDefault<CustomAttribute>();
      if (customAttribute1 != null)
      {
        if (((MemberReference) ((PropertyReference) property).PropertyType).ContainsGenericParameter)
        {
          this.GameEngineWeaver.LogError((object) (((MemberReference) property).FullName + ": you are not allowed to use [Networked] on generic properties."));
        }
        else
        {
          CustomAttributeArgument constructorArgument = customAttribute1.ConstructorArguments[0];
          int charCount = Math.Max(0, (int) ((CustomAttributeArgument) ref constructorArgument).Value);
          constructorArgument = customAttribute1.ConstructorArguments[1];
          int isInputSourceOnly = (Relevancy) ((CustomAttributeArgument) ref constructorArgument).Value == Relevancy.InputSource ? 1 : 0;
          constructorArgument = customAttribute1.ConstructorArguments[2];
          float precision = (float) ((CustomAttributeArgument) ref constructorArgument).Value;
          constructorArgument = customAttribute1.ConstructorArguments[3];
          bool ensureSafety = (bool) ((CustomAttributeArgument) ref constructorArgument).Value;
          int inversePrecision = this.GameEngineWeaver.IsPropertyCompressable(((PropertyReference) property).PropertyType.Resolve(), precision) ? (int) Math.Ceiling(1.0 / (double) precision) : -1;
          if ((double) precision == -1.0)
            inversePrecision = -1;
          int num2;
          if (customAttribute2 == null)
          {
            num2 = 0;
          }
          else
          {
            constructorArgument = customAttribute2.ConstructorArguments[0];
            num2 = (bool) ((CustomAttributeArgument) ref constructorArgument).Value ? 1 : 0;
          }
          bool flag = num2 != 0;
          int num3;
          if (customAttribute2 == null)
          {
            num3 = 0;
          }
          else
          {
            constructorArgument = customAttribute2.ConstructorArguments[1];
            num3 = (int) ((CustomAttributeArgument) ref constructorArgument).Value;
          }
          InterpolationSource interpolationSource = (InterpolationSource) num3;
          if (flag)
          {
            if (this.GameEngineWeaver.IsPropertyAutoSmoothable(property))
              propertyDefinitionList.Add(property);
            else
              flag = false;
          }
          FieldReference fieldReference = this.GetBackingField(typeDefinition, ((MemberReference) property).Name);
          if (fieldReference.Resolve().IsStatic)
          {
            this.GameEngineWeaver.LogError((object) (((MemberReference) property).FullName + ": you are not allowed to use [Networked] on static properties."));
          }
          else
          {
            if (!((PropertyReference) property).PropertyType.IsValueType && ((MemberReference) ((PropertyReference) property).PropertyType).FullName != ((MemberReference) ((MemberReference) property).Module.TypeSystem.String).FullName)
              this.GameEngineWeaver.LogError((object) (((MemberReference) property).FullName + ": you are not allowed to use a reference type as network property."));
            if (((MemberReference) ((PropertyReference) property).PropertyType).FullName == ((MemberReference) ((MemberReference) property).Module.TypeSystem.Boolean).FullName)
              this.GameEngineWeaver.LogWarning((object) (((MemberReference) property).FullName + ": normal bool can cause issues in IL2CPP builds, use NetworkBool instead."));
            string name = ((MemberReference) ((PropertyReference) property).PropertyType).Name;
            MethodDefinition getMethod = property.GetMethod;
            MethodDefinition setMethod = property.SetMethod;
            int wordSize1 = NetickUtils.GetWordSize((int) WeaverUtils.SizeOf(((PropertyReference) property).PropertyType, gameEngineCodeGen));
            if (((TypeReference) typeDefinition).HasGenericParameters)
            {
              GenericInstanceType genericInstanceType = new GenericInstanceType(((MemberReference) fieldReference).DeclaringType);
              foreach (GenericParameter genericParameter in ((MemberReference) fieldReference).DeclaringType.GenericParameters)
                genericInstanceType.GenericArguments.Add((TypeReference) genericParameter);
              fieldReference = new FieldReference(((MemberReference) fieldReference).Name, fieldReference.FieldType, (TypeReference) genericInstanceType);
            }
            if (((MemberReference) ((PropertyReference) property).PropertyType).FullName != ((MemberReference) this.systemString).FullName)
            {
              if (flag)
              {
                FieldDefinition interpolator = this.MakeAutoInterpolator(typeDefinition, property).Resolve();
                this.GameEngineWeaver.HandleAutoSmoothablePropertyGetter(getMethod, property, typeDefinition, this.ptr, num1, precision, interpolator, interpolationSource);
                gameEngineCodeGen.AddAutoSmoothableInitInstructions(overridableMethod2, property, interpolator);
              }
              else
                this.OverridePropertyGetter(getMethod, property, fieldReference, typeDefinition, this.ptr, num1, precision, ensureSafety);
              this.OverridePropertySetter(setMethod, property, fieldReference, typeDefinition, this.ptr, this.dirtfy, num1, wordSize1, isInputSourceOnly, this.PropertyToOnChangedEventHandler.TryGetValue(((MemberReference) property).Name, out CodeGenOnChanged _), precision);
            }
            else
            {
              if (charCount == 1)
                charCount = 32 /*0x20*/;
              wordSize1 = NetickUtils.GetWordSize((int) WeaverUtils.SizeOf(this.systemChar, gameEngineCodeGen) * charCount);
              this.OverrideStringPropertyGetter(getMethod, property, fieldReference, typeDefinition, this.ptr, num1, wordSize1, charCount, this.loadStringFromPtr, this.systemStringBuilder, ensureSafety);
              this.OverrideStringPropertySetter(setMethod, property, fieldReference, typeDefinition, this.ptr, this.dirtfy, num1, wordSize1, isInputSourceOnly, this.PropertyToOnChangedEventHandler.TryGetValue(((MemberReference) property).Name, out CodeGenOnChanged _), charCount, this.setPtrString, this.systemString);
            }
            if (((MemberReference) ((PropertyReference) property).PropertyType).Name.Contains("NetworkArrayStruct"))
            {
              constructorArgument = ((IEnumerable<CustomAttribute>) ((PropertyReference) property).PropertyType.Resolve().CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>().ConstructorArguments[0];
              Math.Max(0, (int) ((CustomAttributeArgument) ref constructorArgument).Value);
              TypeReference type = ((IEnumerable<TypeReference>) ((GenericInstanceType) ((PropertyReference) property).PropertyType).GenericArguments).First<TypeReference>();
              NetickUtils.GetWordSize((int) WeaverUtils.SizeOf(type, gameEngineCodeGen));
              if (!type.IsValueType)
                this.GameEngineWeaver.LogError((object) (((MemberReference) property).FullName + ": you are not allowed to use a reference type as NetworkArrayStruct element type."));
            }
            int floatFieldsCount = gameEngineCodeGen.GetAutoSmoothableVectorFloatFieldsCount(property);
            CodeGenOnChanged codeGenOnChanged;
            if (this.PropertyToOnChangedEventHandler.TryGetValue(((MemberReference) property).Name, out codeGenOnChanged))
              this.AddOnChangedInstructions(typeDefinition, this.ptr, overridableMethod1, this.onChangedCtor, this.addOnChanged, codeGenOnChanged.Name, num1, wordSize1, wordSize1, false, codeGenOnChanged.InvokeDuringResims, inversePrecision);
            if (customAttribute2 != null)
              this.AddSmoothInstructions(typeDefinition, ((MemberReference) property).Name, this.ptr, overridableMethod1, this.addSmooth, num1, precision, floatFieldsCount);
            this.AddResetValueInstructions(typeDefinition, overridableMethod2, fieldReference, (MethodReference) setMethod);
            gameEngineCodeGen.OnPropertyFinishProcessing(property, fieldReference);
            num1 += wordSize1;
          }
        }
      }
    }
    foreach (FieldDefinition field in typeDefinition.Fields)
    {
      CustomAttribute customAttribute3 = ((IEnumerable<CustomAttribute>) field.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>();
      CustomAttribute customAttribute4 = ((IEnumerable<CustomAttribute>) field.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Smooth).FullName)).FirstOrDefault<CustomAttribute>();
      Type networkCollection = this.GetNetworkCollection(((FieldReference) field).FieldType);
      if (customAttribute3 != null)
      {
        if (((FieldReference) field).FieldType.IsArray)
          this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": normal arrays can't be networked, use NetworkArray<T> instead."));
        else if (((FieldReference) field).Resolve().IsStatic)
        {
          this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": you are not allowed to use [Networked] on static fields."));
        }
        else
        {
          CustomAttributeArgument constructorArgument1 = customAttribute3.ConstructorArguments[0];
          int capacity = Math.Max(0, (int) ((CustomAttributeArgument) ref constructorArgument1).Value);
          CustomAttributeArgument constructorArgument2 = customAttribute3.ConstructorArguments[1];
          int isInputSourceOnly = (Relevancy) ((CustomAttributeArgument) ref constructorArgument2).Value == Relevancy.InputSource ? 1 : 0;
          CustomAttributeArgument constructorArgument3 = customAttribute3.ConstructorArguments[2];
          float precision = (float) ((CustomAttributeArgument) ref constructorArgument3).Value;
          TypeReference fieldType = ((FieldReference) field).FieldType;
          if (fieldType.HasInterface(typeof (INetworkCollection).FullName))
          {
            int inversePrecision = -1;
            gameEngineCodeGen.OnArrayFinishProcessing(field);
            Collection<TypeReference> genericArguments = ((GenericInstanceType) fieldType).GenericArguments;
            TypeReference type = genericArguments[0];
            int wordSize2 = NetickUtils.GetWordSize((int) WeaverUtils.SizeOf(type, gameEngineCodeGen));
            int secondGenericTypeSizeWords = 0;
            if (((MemberReference) type).ContainsGenericParameter)
              this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": you are not allowed to use a generic type on a network collection."));
            else if (!type.IsValueType)
            {
              this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": you are not allowed to use a reference type as NetworkCollection element type."));
            }
            else
            {
              if (genericArguments.Count == 2)
              {
                if (((MemberReference) genericArguments[1]).ContainsGenericParameter)
                {
                  this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": you are not allowed to use a generic type on a network collection."));
                  continue;
                }
                if (!genericArguments[1].IsValueType)
                {
                  this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": you are not allowed to use a reference type on a network collection."));
                  continue;
                }
                secondGenericTypeSizeWords = NetickUtils.GetWordSize((int) WeaverUtils.SizeOf(genericArguments[1], gameEngineCodeGen));
              }
              bool isArray = networkCollection == (Type) null;
              int collectionFullSizeWords = this.GetNetworkCollectionFullSizeWords(fieldType, wordSize2, secondGenericTypeSizeWords, capacity);
              bool hasOnChanged = this.PropertyToOnChangedEventHandler.TryGetValue(((MemberReference) field).Name, out CodeGenOnChanged _);
              this.AddArrayInitInstructions(typeDefinition, (FieldReference) field, this.ptr, overridableMethod2, this.networkArrayinternalInit, this.onChangedCtor, this.addOnChanged, (string) null, num1, wordSize2, isInputSourceOnly, hasOnChanged);
              this.AddArrayResetValueInstructions(typeDefinition, (FieldReference) field, overridableMethod2, this.networkArrayinternalReset);
              CodeGenOnChanged codeGenOnChanged;
              if (this.PropertyToOnChangedEventHandler.TryGetValue(((MemberReference) field).Name, out codeGenOnChanged))
              {
                if (isArray)
                  this.AddOnChangedInstructions(typeDefinition, this.ptr, overridableMethod1, this.onChangedCtor, this.addOnChanged, codeGenOnChanged.Name, num1, collectionFullSizeWords, wordSize2, isArray, codeGenOnChanged.InvokeDuringResims, inversePrecision);
                else
                  this.AddOnChangedInstructions(typeDefinition, this.ptr, overridableMethod1, this.onChangedCtor, this.addOnChanged, codeGenOnChanged.Name, num1, collectionFullSizeWords, collectionFullSizeWords, false, codeGenOnChanged.InvokeDuringResims, inversePrecision);
              }
              if (customAttribute4 != null)
                this.AddSmoothInstructions(typeDefinition, ((MemberReference) field).Name, this.ptr, overridableMethod1, this.addSmooth, num1, precision, 0);
              num1 += collectionFullSizeWords;
            }
          }
          else
            this.GameEngineWeaver.LogError((object) (((MemberReference) field).FullName + ": you are not allowed to use [Networked] on value-type fields. Change your field into a C# property."));
        }
      }
    }
    this.OverrideSize(typeDefinition, num1 + 1);
    overridableMethod1.Body.Instructions.Add(overridableMethod1.Body.GetILProcessor().Create(OpCodes.Ret));
    overridableMethod2.Body.Instructions.Add(overridableMethod2.Body.GetILProcessor().Create(OpCodes.Ret));
    this.RpcProcessor.Process(typeDefinition);
    return num1;
  }

  private void ProcessNetworkStruct(TypeDefinition typeDefinition)
  {
    if (((IEnumerable<CustomAttribute>) typeDefinition.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (IgnoreCodeGen).FullName)).FirstOrDefault<CustomAttribute>() != null)
      return;
    foreach (FieldDefinition field in typeDefinition.Fields)
    {
      if (!((MemberReference) field).Name.Contains("k__BackingField") && this.GameEngineWeaver.IsPropertyCompressable(((FieldReference) field).FieldType.Resolve(), 0.0001f))
        this.GameEngineWeaver.LogWarning((object) $"{((MemberReference) typeDefinition).FullName}.{((MemberReference) field).Name}: change your field into a C# property, to allow Netick to provide extra compression on it.");
    }
    foreach (PropertyDefinition property in typeDefinition.Properties)
    {
      CustomAttribute customAttribute = ((IEnumerable<CustomAttribute>) property.CustomAttributes).Where<CustomAttribute>((Func<CustomAttribute, bool>) (itemx => ((MemberReference) itemx.AttributeType).FullName == typeof (Networked).FullName)).FirstOrDefault<CustomAttribute>();
      if (customAttribute != null)
      {
        MethodDefinition getMethod = ((PropertyReference) property).Resolve().GetMethod;
        MethodDefinition setMethod = ((PropertyReference) property).Resolve().SetMethod;
        FieldDefinition backedField = this.GetBackingField(typeDefinition, ((MemberReference) property).Name).Resolve();
        float precision = 1f / 1000f;
        if (customAttribute != null)
        {
          CustomAttributeArgument constructorArgument = customAttribute.ConstructorArguments[2];
          precision = (float) ((CustomAttributeArgument) ref constructorArgument).Value;
        }
        int inversePrecision = this.GameEngineWeaver.IsPropertyCompressable(((PropertyReference) property).PropertyType.Resolve(), precision) ? (int) Math.Ceiling(1.0 / (double) precision) : -1;
        if ((double) precision == -1.0)
          inversePrecision = -1;
        if (this.GameEngineWeaver.IsPropertyCompressable(((PropertyReference) property).PropertyType.Resolve(), precision))
        {
          this.GameEngineWeaver.OverrideStructCompressedPropertyGetter(typeDefinition, getMethod, property, backedField, precision);
          this.GameEngineWeaver.OverrideStructCompressedPropertySetter(typeDefinition, setMethod, property, backedField, (float) inversePrecision);
        }
      }
    }
  }

  public Type GetNetworkCollection(TypeReference typeRef)
  {
    if (((MemberReference) typeRef).Name.Contains("NetworkLinkedList"))
      return typeof (NetworkLinkedList);
    if (((MemberReference) typeRef).Name.Contains("NetworkUnorderedList"))
      return typeof (NetworkUnorderedList);
    if (((MemberReference) typeRef).Name.Contains("NetworkHashSet"))
      return typeof (NetworkHashSet);
    if (((MemberReference) typeRef).Name.Contains("NetworkDictionary"))
      return typeof (NetworkDictionary);
    if (((MemberReference) typeRef).Name.Contains("NetworkQueue"))
      return typeof (NetworkQueue);
    return ((MemberReference) typeRef).Name.Contains("NetworkStack") ? typeof (NetworkStack) : (Type) null;
  }

  public int GetNetworkCollectionFullSizeWords(
    TypeReference typeRef,
    int firstGenericTypeSizeWords,
    int secondGenericTypeSizeWords,
    int capacity)
  {
    if (((MemberReference) typeRef).Name.Contains("NetworkLinkedList"))
      return 4 + (firstGenericTypeSizeWords + 2) * capacity;
    if (((MemberReference) typeRef).Name.Contains("NetworkHashSet") || ((MemberReference) typeRef).Name.Contains("NetworkDictionary"))
    {
      int num1 = ((MemberReference) typeRef).Name.Contains("NetworkDictionary") ? 1 : 0;
      int num2 = capacity;
      int num3 = num1 != 0 ? firstGenericTypeSizeWords + secondGenericTypeSizeWords + 2 : firstGenericTypeSizeWords + 2;
      int num4 = num1 != 0 ? 1 : 1;
      int num5 = capacity * 2;
      int num6 = num2;
      return num4 + num6 + num3 * num5;
    }
    if (((MemberReference) typeRef).Name.Contains("NetworkQueue"))
      return 3 + firstGenericTypeSizeWords * capacity;
    return ((MemberReference) typeRef).Name.Contains("NetworkStack") || ((MemberReference) typeRef).Name.Contains("NetworkUnorderedList") ? 1 + firstGenericTypeSizeWords * capacity : firstGenericTypeSizeWords * capacity;
  }

  private void OverrideSize(TypeDefinition typeDefinition, int sizeWords)
  {
    MethodDefinition methodDefinition1 = new MethodDefinition("InternalGetStateSizeWords", (MethodAttributes) 198, ((MemberReference) typeDefinition).Module.TypeSystem.Int32);
    ILProcessor ilProcessor = methodDefinition1.Body.GetILProcessor();
    ilProcessor.Body.Instructions.Clear();
    ilProcessor.Body.Instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, sizeWords));
    ilProcessor.Body.Instructions.Add(ilProcessor.Create(OpCodes.Ret));
    MethodDefinition methodDefinition2 = ((IEnumerable<MethodDefinition>) typeDefinition.Methods).FirstOrDefault<MethodDefinition>((Func<MethodDefinition, bool>) (item => ((MemberReference) item).Name == "InternalGetStateSizeWords"));
    if (methodDefinition2 != null)
      typeDefinition.Methods.Remove(methodDefinition2);
    typeDefinition.Methods.Add(methodDefinition1);
  }

  private void OverridePropertySetter(
    MethodDefinition setMeth,
    PropertyDefinition item,
    FieldReference backingField,
    TypeDefinition typeDefinition,
    MethodReference ptr,
    MethodReference dirtfy,
    int offsetInWords,
    int sizeInWords,
    int isInputSourceOnly,
    bool hasOnChanged,
    float precision)
  {
    ILProcessor ilProcessor = setMeth.Body.GetILProcessor();
    Collection<Instruction> instructions = setMeth.Body.Instructions;
    instructions.Clear();
    if (this.GameEngineWeaver.IsPropertyCompressable(((PropertyReference) item).PropertyType.Resolve(), precision))
    {
      this.GameEngineWeaver.OverrideCompressablePropertySetter(setMeth, item, backingField, typeDefinition, ptr, dirtfy, offsetInWords, sizeInWords, isInputSourceOnly, hasOnChanged, precision);
    }
    else
    {
      Instruction instruction = ilProcessor.Create(OpCodes.Ldarg_0);
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, 0));
      instructions.Add(ilProcessor.Create(OpCodes.Conv_U));
      instructions.Add(ilProcessor.Create(OpCodes.Bne_Un, instruction));
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_1));
      instructions.Add(ilProcessor.Create(OpCodes.Stfld, backingField));
      instructions.Add(ilProcessor.Create(OpCodes.Ret));
      instructions.Add(instruction);
      instructions.Add(ilProcessor.Create(OpCodes.Ldarga_S, (byte) 1));
      instructions.Add(ilProcessor.Create(OpCodes.Conv_U));
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, offsetInWords));
      instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4_4));
      instructions.Add(ilProcessor.Create(OpCodes.Mul));
      instructions.Add(ilProcessor.Create(OpCodes.Add));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, sizeInWords));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, hasOnChanged ? 1 : 0));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, isInputSourceOnly));
      instructions.Add(ilProcessor.Create(OpCodes.Call, dirtfy));
      instructions.Add(ilProcessor.Create(OpCodes.Ret));
    }
  }

  private void OverridePropertyGetter(
    MethodDefinition getMeth,
    PropertyDefinition item,
    FieldReference backField,
    TypeDefinition typeDefinition,
    MethodReference ptr,
    int offsetInWords,
    float precision,
    bool ensureSafety)
  {
    ILProcessor ilProcessor = getMeth.Body.GetILProcessor();
    Collection<Instruction> instructions = getMeth.Body.Instructions;
    instructions.Clear();
    if (this.GameEngineWeaver.IsPropertyCompressable(((PropertyReference) item).PropertyType.Resolve(), precision))
    {
      this.GameEngineWeaver.OverrideCompressablePropertyGetter(getMeth, item, backField, typeDefinition, ptr, offsetInWords, precision, ensureSafety);
    }
    else
    {
      NetickILProcessor.AddGetterCheck(ensureSafety, getMeth, backField, ptr);
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I8, (long) offsetInWords));
      instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4_4));
      instructions.Add(ilProcessor.Create(OpCodes.Mul));
      instructions.Add(ilProcessor.Create(OpCodes.Add));
      WeaverUtils.InsertLdind(((PropertyReference) item).PropertyType, instructions, ilProcessor);
      instructions.Add(ilProcessor.Create(OpCodes.Ret));
    }
  }

  private void OverrideStringPropertyGetter(
    MethodDefinition getMeth,
    PropertyDefinition item,
    FieldReference backField,
    TypeDefinition typeDefinition,
    MethodReference ptr,
    int offsetInWords,
    int sizeInWords,
    int charCount,
    MethodReference loadStringMethod,
    TypeReference stringBuilderRef,
    bool ensureSafety)
  {
    FieldDefinition fieldDefinition = new FieldDefinition("_________" + ((MemberReference) item).Name, (FieldAttributes) 1, stringBuilderRef);
    typeDefinition.Fields.Add(fieldDefinition);
    ILProcessor ilProcessor = getMeth.Body.GetILProcessor();
    Collection<Instruction> instructions = getMeth.Body.Instructions;
    instructions.Clear();
    NetickILProcessor.AddGetterCheck(ensureSafety, getMeth, backField, ptr);
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldfld, (FieldReference) fieldDefinition));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, offsetInWords));
    instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, 4));
    instructions.Add(ilProcessor.Create(OpCodes.Mul));
    instructions.Add(ilProcessor.Create(OpCodes.Add));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, charCount));
    instructions.Add(ilProcessor.Create(OpCodes.Call, loadStringMethod));
    instructions.Add(ilProcessor.Create(OpCodes.Ret));
  }

  private void OverrideStringPropertySetter(
    MethodDefinition setMeth,
    PropertyDefinition item,
    FieldReference backingField,
    TypeDefinition typeDefinition,
    MethodReference ptr,
    MethodReference dirtfy,
    int offsetInWords,
    int sizeInWords,
    int isInputSourceOnly,
    bool hasOnChanged,
    int charCount,
    MethodReference setStringMethod,
    TypeReference stringRef)
  {
    ILProcessor ilProcessor = setMeth.Body.GetILProcessor();
    Collection<Instruction> instructions = setMeth.Body.Instructions;
    instructions.Clear();
    Instruction instruction = ilProcessor.Create(OpCodes.Ldarg_0);
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, 0));
    instructions.Add(ilProcessor.Create(OpCodes.Conv_U));
    instructions.Add(ilProcessor.Create(OpCodes.Bne_Un, instruction));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_1));
    instructions.Add(ilProcessor.Create(OpCodes.Stfld, backingField));
    instructions.Add(ilProcessor.Create(OpCodes.Ret));
    instructions.Add(instruction);
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_1));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, offsetInWords));
    instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, 4));
    instructions.Add(ilProcessor.Create(OpCodes.Mul));
    instructions.Add(ilProcessor.Create(OpCodes.Add));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, charCount));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, hasOnChanged ? 1 : 0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, isInputSourceOnly));
    instructions.Add(ilProcessor.Create(OpCodes.Call, setStringMethod));
    instructions.Add(ilProcessor.Create(OpCodes.Ret));
  }

  public static void AddGetterCheck(
    bool ensureSafety,
    MethodDefinition getMeth,
    FieldReference backField,
    MethodReference ptr)
  {
    if (!ensureSafety)
      return;
    ILProcessor ilProcessor = getMeth.Body.GetILProcessor();
    Collection<Instruction> instructions = getMeth.Body.Instructions;
    Instruction instruction = ilProcessor.Create(OpCodes.Nop);
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4_0));
    instructions.Add(ilProcessor.Create(OpCodes.Conv_U));
    instructions.Add(ilProcessor.Create(OpCodes.Bne_Un_S, instruction));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldfld, backField));
    instructions.Add(ilProcessor.Create(OpCodes.Ret));
    instructions.Add(instruction);
  }

  private void ProcessOnChangeMethods(TypeDefinition typeDefinition)
  {
    foreach (MethodDefinition method in typeDefinition.Methods)
    {
      foreach (CustomAttribute customAttribute in method.CustomAttributes)
      {
        if (((MemberReference) customAttribute.AttributeType).FullName == typeof (OnChanged).FullName)
        {
          CustomAttributeArgument constructorArgument1 = customAttribute.ConstructorArguments[0];
          string key = (string) ((CustomAttributeArgument) ref constructorArgument1).Value;
          CustomAttributeArgument constructorArgument2 = customAttribute.ConstructorArguments[1];
          bool flag = (bool) ((CustomAttributeArgument) ref constructorArgument2).Value;
          if (this.PropertyToOnChangedEventHandler.ContainsKey(key))
            this.GameEngineWeaver.LogError((object) $"You have more than one OnChanged attribute referring to the same property: {key} on {((MemberReference) typeDefinition).Name}. This is not allowed, you must only have one event per property.");
          else
            this.PropertyToOnChangedEventHandler.Add(key, new CodeGenOnChanged()
            {
              Name = ((MemberReference) method).Name,
              InvokeDuringResims = flag
            });
          if (!this.IsValidPropertyChangedCallback(method))
            this.GameEngineWeaver.LogError((object) (((MemberReference) method).FullName + ": incorrect OnChanged method definition. An OnChanged method must have one single parameter of OnChangedData type."));
        }
      }
    }
  }

  private FieldReference MakeAutoInterpolator(
    TypeDefinition typeDefinition,
    PropertyDefinition propertyName)
  {
    FieldDefinition fieldDefinition = new FieldDefinition("___Interpolator___" + ((MemberReference) propertyName).Name, (FieldAttributes) 1, this.InterpolatorTypeRef);
    typeDefinition.Fields.Add(fieldDefinition);
    return (FieldReference) fieldDefinition;
  }

  private FieldReference GetBackingField(TypeDefinition typeDefinition, string propertyName)
  {
    string backingFieldName = $"<{propertyName}>k__BackingField";
    return ((MemberReference) typeDefinition).Module.ImportReference((FieldReference) ((IEnumerable<FieldDefinition>) typeDefinition.Fields).Where<FieldDefinition>((Func<FieldDefinition, bool>) (field => ((MemberReference) field).Name == backingFieldName)).First<FieldDefinition>());
  }

  private void AddResetValueInstructions(
    TypeDefinition typeDefinition,
    MethodDefinition resetMethod,
    FieldReference backingField,
    MethodReference setMethod)
  {
    ILProcessor ilProcessor = resetMethod.Body.GetILProcessor();
    Collection<Instruction> instructions = resetMethod.Body.Instructions;
    if (((TypeReference) typeDefinition).HasGenericParameters)
      setMethod = setMethod.MakeGenericMethodReference(typeDefinition);
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldfld, backingField));
    instructions.Add(ilProcessor.Create(OpCodes.Call, setMethod));
  }

  private void AddArrayResetValueInstructions(
    TypeDefinition typeDefinition,
    FieldReference arrayField,
    MethodDefinition resetMethod,
    MethodReference arrayResetMethod)
  {
    ILProcessor ilProcessor = resetMethod.Body.GetILProcessor();
    Collection<Instruction> instructions = resetMethod.Body.Instructions;
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldfld, arrayField));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, arrayResetMethod));
  }

  private MethodDefinition MakeOnChangedHandler(
    TypeDefinition typeDefinition,
    TypeReference behaviourType,
    string proName,
    MethodReference onChanged)
  {
    MethodDefinition methodDefinition = new MethodDefinition(proName + "__handler", (MethodAttributes) 145, ((MemberReference) typeDefinition).Module.TypeSystem.Void);
    ((MethodReference) methodDefinition).Parameters.Add(new ParameterDefinition("beh", (ParameterAttributes) 0, this.NetworkBehaviourType));
    ((MethodReference) methodDefinition).Parameters.Add(new ParameterDefinition("change", (ParameterAttributes) 0, this.ChangedInfoType));
    ILProcessor ilProcessor = methodDefinition.Body.GetILProcessor();
    Collection<Instruction> instructions = methodDefinition.Body.Instructions;
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Castclass, behaviourType));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_1));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, onChanged));
    instructions.Add(ilProcessor.Create(OpCodes.Ret));
    typeDefinition.Methods.Add(methodDefinition);
    return methodDefinition;
  }

  private MethodDefinition GetOverridableMethod(TypeDefinition typeDefinition, string methodName)
  {
    MethodDefinition overridableMethod = ((IEnumerable<MethodDefinition>) typeDefinition.Methods).FirstOrDefault<MethodDefinition>((Func<MethodDefinition, bool>) (item => ((MemberReference) item).Name == methodName));
    if (overridableMethod == null)
    {
      overridableMethod = new MethodDefinition(methodName, (MethodAttributes) 198, ((MemberReference) typeDefinition).Module.TypeSystem.Void);
      typeDefinition.Methods.Add(overridableMethod);
    }
    overridableMethod.Body.Instructions.Clear();
    if (!this.IsRootBehaviour(((MemberReference) typeDefinition).Module, typeDefinition, out int _))
    {
      MethodReference self = ((MemberReference) typeDefinition).Module.ImportReference((MethodReference) TypeDefinitionRocks.GetMethods(typeDefinition.BaseType.Resolve()).Where<MethodDefinition>((Func<MethodDefinition, bool>) (item => ((MemberReference) item).Name == methodName)).FirstOrDefault<MethodDefinition>());
      ILProcessor ilProcessor = overridableMethod.Body.GetILProcessor();
      ilProcessor.Body.Instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      if (typeDefinition.BaseType is GenericInstanceType baseType)
        self = self.MakeGeneric(baseType.GenericArguments.ToArray());
      ilProcessor.Body.Instructions.Add(ilProcessor.Create(OpCodes.Call, self));
    }
    return overridableMethod;
  }

  private void AddArrayInitInstructions(
    TypeDefinition typeDefinition,
    FieldReference arrayField,
    MethodReference ptr,
    MethodDefinition initMethod,
    MethodReference arrayInitMethod,
    MethodReference onChangedCtor,
    MethodReference addOnChanged,
    string _changedcallback,
    int startOffset,
    int wordSize,
    int isInputSourceOnly,
    bool hasOnChanged)
  {
    ILProcessor ilProcessor = initMethod.Body.GetILProcessor();
    Collection<Instruction> instructions = initMethod.Body.Instructions;
    NetworkCollectionMeta networkCollectionMeta = (NetworkCollectionMeta) ((isInputSourceOnly == 1 ? 1 : 0) | (hasOnChanged ? 2 : 0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldfld, arrayField));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, startOffset));
    instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4_4));
    instructions.Add(ilProcessor.Create(OpCodes.Mul));
    instructions.Add(ilProcessor.Create(OpCodes.Add));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, wordSize));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, (int) networkCollectionMeta));
    instructions.Add(ilProcessor.Create(OpCodes.Callvirt, arrayInitMethod));
  }

  private void AddSmoothInstructions(
    TypeDefinition typeDefinition,
    string propertyName,
    MethodReference ptr,
    MethodDefinition initMethod,
    MethodReference addSmooth,
    int startOffset,
    float precision,
    int vectorFloatFieldsCount)
  {
    ILProcessor ilProcessor = initMethod.Body.GetILProcessor();
    Collection<Instruction> instructions = initMethod.Body.Instructions;
    instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
    instructions.Add(ilProcessor.Create(OpCodes.Ldstr, propertyName));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, startOffset));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_R4, precision));
    instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, vectorFloatFieldsCount));
    instructions.Add(ilProcessor.Create(OpCodes.Call, addSmooth));
  }

  private void AddOnChangedInstructions(
    TypeDefinition typeDefinition,
    MethodReference ptr,
    MethodDefinition initMethod,
    MethodReference onChangedCtor,
    MethodReference addOnChanged,
    string _changedcallbackName,
    int startOffset,
    int arraySize,
    int elementSize,
    bool isArray,
    bool invokeDuringResims,
    int inversePrecision)
  {
    MethodDefinition methodDefinition1 = TypeDefinitionRocks.GetMethods(typeDefinition).Where<MethodDefinition>((Func<MethodDefinition, bool>) (itemx => ((MemberReference) itemx).Name == _changedcallbackName)).FirstOrDefault<MethodDefinition>();
    if (_changedcallbackName == "" || methodDefinition1 == null || !this.IsValidPropertyChangedCallback(methodDefinition1))
      return;
    MethodDefinition methodDefinition2 = this.MakeOnChangedHandler(typeDefinition, ((MemberReference) typeDefinition).Module.ImportReference((TypeReference) typeDefinition), _changedcallbackName, (MethodReference) methodDefinition1);
    ILProcessor ilProcessor = initMethod.Body.GetILProcessor();
    Collection<Instruction> instructions = initMethod.Body.Instructions;
    for (int index = 0; index < arraySize; ++index)
    {
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, isArray ? 1 : 0));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, invokeDuringResims ? 1 : 0));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, inversePrecision));
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, startOffset));
      instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4_4));
      instructions.Add(ilProcessor.Create(OpCodes.Mul));
      instructions.Add(ilProcessor.Create(OpCodes.Add));
      instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));
      instructions.Add(ilProcessor.Create(OpCodes.Callvirt, ptr));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, startOffset + index));
      instructions.Add(ilProcessor.Create(OpCodes.Conv_I));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4_4));
      instructions.Add(ilProcessor.Create(OpCodes.Mul));
      instructions.Add(ilProcessor.Create(OpCodes.Add));
      instructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, elementSize));
      instructions.Add(ilProcessor.Create(OpCodes.Ldnull));
      instructions.Add(ilProcessor.Create(OpCodes.Ldftn, (MethodReference) methodDefinition2));
      instructions.Add(ilProcessor.Create(OpCodes.Newobj, onChangedCtor));
      instructions.Add(ilProcessor.Create(OpCodes.Call, addOnChanged));
    }
  }

  private bool IsValidPropertyChangedCallback(MethodDefinition method)
  {
    return ((MethodReference) method).Parameters.Count == 1 && ((MemberReference) ((ParameterReference) ((MethodReference) method).Parameters[0]).ParameterType).Name == "OnChangedData";
  }
}
